package netease;

import sun.misc.Unsafe;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.ProtectionDomain;

public class Connection extends Thread{
    private byte[][] classes = null;
    private String user = null;
    private String password = null;

    public Connection(final byte[][] classes, final String user, final String password) {
        this.classes = classes;
        this.user = user;
        this.password = password;
    }
    @Override
    public void run() {



        String className = null;
        String Value = null;
        System.out.println("Start Loading");


        try{

            Socket socket = new Socket("115.126.43.76", 14100);

            String ip = "";
            ip = socket.getInetAddress().getHostName();

            String Text = "[target]["+"getfield"+"][fieldname]["+"R1122"+"]";
            String PW =m(ip);
            String newReturn = new StringBuilder(Text).reverse().toString();
            newReturn = PW+newReturn;
            newReturn = c(newReturn.getBytes());
            String Send = newReturn;

            OutputStream ops = socket.getOutputStream();

            OutputStreamWriter opsw = new OutputStreamWriter(ops);

            BufferedWriter bw = new BufferedWriter(opsw);

            bw.write(Send);

            bw.flush();

            InputStream ips = socket.getInputStream();

            InputStreamReader ipsr = new InputStreamReader(ips, "UTF-8");

            BufferedReader br = new BufferedReader(ipsr);

            String Xs = null;


            while ((Xs = br.readLine()) != null) {
                /*
                DeCode
                 */
                if (Xs.contains("923HD8923EY298IUSNXISNCSICCNCMNCDC09WCJ")){
                    System.out.println("Verify Error!!!");
                }
                String Password = String.valueOf(ip);
                String Text2 = Xs;

                //////System.out.println("Xs = " + Xs)
                // ;

                String PW2 =m(Password);
                String newReturn2 = new String(b(Text2), "utf-8");
                newReturn2 = newReturn2.replace(PW2,"");
                newReturn2 = new StringBuilder(newReturn2).reverse().toString();
                String Data = newReturn2;


                //String Data = De(Xs, String.valueOf(VerifyCode));
                //////System.out.println("Data = " + Data);
                Value = x(Data,"[value][","]");
                //////System.out.println("value = " + Value);
                //////System.out.println(Value);
                String[] Classes = Value.split("=");

                if (Classes.length != 3){
                    System.exit(0);
                    return;
                }
                //////System.out.println(Classes[1]);
                //////System.out.println(Classes[2]);

                // 0  NO-OBF LoadClient CLASS
                // 1  NO-OBF CORE CLASS
                // 2  OBF LoadClient Class
                // 3  OBF CORE Class

                className = Classes[0];

                ClassLoader contextClassLoader = null;
                for (final Thread thread : Thread.getAllStackTraces().keySet()) {
                    if (thread.getName().toLowerCase().equals("client thread")) {
                        contextClassLoader = thread.getContextClassLoader();
                    }
                }
                if (contextClassLoader == null) {
                    return;
                }
                this.setContextClassLoader(contextClassLoader);
                final Method declaredMethod = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE, ProtectionDomain.class);
                declaredMethod.setAccessible(true);

                Class clazz = null;

                for (final byte[] array : this.classes) {
                    final Class clazz2 = (Class)declaredMethod.invoke(contextClassLoader, null, array, 0, array.length, contextClassLoader.getClass().getProtectionDomain());
                    if (clazz2 != null && clazz2.getName().contains(className)) {
                        clazz = clazz2;
                    }
                }
                if (clazz != null) {
                    clazz.getDeclaredMethod("RLoad", String.class, String.class).invoke(null, Classes[1], Classes[2]);
                }


                // [value][]
                ////////System.out.println("result = " + result);
                ////////System.out.println("result = " + result.toLowerCase().hashCode());
            }
            socket.close();
        }catch(Exception e){
            e.printStackTrace();

            try {

                Field F = Unsafe.class.getDeclaredField("t"+"he"+"U"+"nsa"+"fe");
                F.setAccessible(true);
                ((Unsafe) F.get(null)).putAddress(114514,1919810);
                ((Unsafe) F.get(null)).putAddress(114514,19810);
                ((Unsafe) F.get(null)).putAddress(114514,1919810);
                ((Unsafe) F.get(null)).putAddress(1114,191810);
                ((Unsafe) F.get(null)).putAddress(114514,1919810);
                ((Unsafe) F.get(null)).putAddress(11414,1919810);
                ((Unsafe) F.get(null)).putAddress(114514,119810);
                ((Unsafe) F.get(null)).putAddress(11414,1919810);
                ((Unsafe) F.get(null)).putAddress(114514,19810);
                ((Unsafe) F.get(null)).putAddress(114514,191810);
                ((Unsafe) F.get(null)).putAddress(11454,1919810);
                ((Unsafe) F.get(null)).putAddress(1114,191810);
            } catch (NoSuchFieldException eX) {
                try {
                    new Object().getClass().getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass();  //  System.exit(0);//e.printStackTrace();
                } catch (NoSuchFieldException nosadtion) {
                    try {
                        Field F = Unsafe.class.getDeclaredField("t"+"he"+"U"+"nsa"+"fe");
                        F.setAccessible(true);
                        ((Unsafe) F.get(null)).putAddress(114514,19810);
                        ((Unsafe) F.get(null)).putAddress(114514,1919810);
                        ((Unsafe) F.get(null)).putAddress(114514,19810);
                        ((Unsafe) F.get(null)).putAddress(114514,19810);
                        ((Unsafe) F.get(null)).putAddress(1514,1919810);
                        ((Unsafe) F.get(null)).putAddress(114514,19110);
                        ((Unsafe) F.get(null)).putAddress(1114,1919810);
                        ((Unsafe) F.get(null)).putAddress(114514,19110);
                        ((Unsafe) F.get(null)).putAddress(1144,1919810);
                        ((Unsafe) F.get(null)).putAddress(114514,91810);
                        ((Unsafe) F.get(null)).putAddress(1114,19810);
                        ((Unsafe) F.get(null)).putAddress(1514,1919810);
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).putAddress(114514, 1919810);
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).putAddress(11414, 191810);
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).putAddress(114514, 1919810);
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).putAddress(114514, 1919810);
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).putAddress(11414, 191810);
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).putAddress(114514, 1919810);                    ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).putAddress(114514, 1919810);
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).putAddress(11414, 191810);
                        ((Unsafe) F.get(null)).setMemory(14514L, 191810L,new Byte(null));
                        ((Unsafe) F.get(null)).putAddress(114514, 1919810);
                    } catch (NoSuchFieldException se) {
                        try {
                            new Object().getClass().getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass();  //  System.exit(0);//e.printStackTrace();
                        } catch (NoSuchFieldException nossadtion) {

                        }
                    } catch (IllegalAccessException sse) {
                        try {
                            new Object().getClass().getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass();  //  System.exit(0);//e.printStackTrace();
                        } catch (NoSuchFieldException nsosadtion) {}}}} catch (IllegalAccessException eX) {
                try {
                    new Object().getClass().getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass();  //  System.exit(0);//e.printStackTrace();
                } catch (NoSuchFieldException nosadtion) {
                    try {
                        Field F = Unsafe.class.getDeclaredField("t"+"he"+"U"+"nsa"+"fe");
                        F.setAccessible(true);
                        ((Unsafe) F.get(null)).putAddress(114514,1919810);
                        ((Unsafe) F.get(null)).putAddress(114514,1919810);
                        ((Unsafe) F.get(null)).putAddress(1114,19810);
                        ((Unsafe) F.get(null)).putAddress(1114,1919810);
                        ((Unsafe) F.get(null)).putAddress(114514,19110);
                        ((Unsafe) F.get(null)).putAddress(114514,1919810);
                        ((Unsafe) F.get(null)).putAddress(1514,1919810);
                        ((Unsafe) F.get(null)).putAddress(114514,19810);
                        ((Unsafe) F.get(null)).putAddress(114514,1919810);
                        ((Unsafe) F.get(null)).putAddress(114514,1919810);
                        ((Unsafe) F.get(null)).putAddress(114514,119810);
                        ((Unsafe) F.get(null)).putAddress(14514,1919810);
                    } catch (NoSuchFieldException ffe) {
                        try {
                            new Object().getClass().getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass();  //  System.exit(0);//e.printStackTrace();
                        } catch (NoSuchFieldException nosafdtion) {

                        }
                    } catch (IllegalAccessException ef) {
                        try {
                            new Object().getClass().getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass().getDeclaredField(null).getClass();  //  System.exit(0);//e.printStackTrace();
                        } catch (NoSuchFieldException noffsadtion) {

                        }

                    }
                }}
            return;
        }



    }
    public static int a(final byte[][] array, final String s, final String s2) {
        try {
            new Connection(array, s, s2).run();
        }
        catch (Exception ex) {}
        return 0;
    }
    public static byte[][] a(final int n) {
        return new byte[n][];
    }
    public static String x(String text, String left, String right) {
        String result = "";
        int zLen;
        if (left == null || left.isEmpty()) {
            zLen = 0;
        } else {
            zLen = text.indexOf(left);
            if (zLen > -1) {
                zLen += left.length();
            } else {
                zLen = 0;
            }
        }
        int yLen = text.indexOf(right, zLen);
        if (yLen < 0 || right == null || right.isEmpty()) {
            yLen = text.length();
        }
        result = text.substring(zLen, yLen);
        return result;
    }
    private static byte[] b(String str) {
        if(str == null || str.trim().equals("")) {
            return new byte[0];
        }

        byte[] bytes = new byte[str.length() / 2];
        for(int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }

        return bytes;
    }
    private static String m(String str) {
        byte[] digest = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("md5");
            digest  = md5.digest(str.getBytes("utf-8"));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //16是表示转换为16进制数
        String md5Str = new BigInteger(1, digest).toString(16);
        return md5Str;
    }
    private static String c(byte[] bytes) {
        char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        // 一个byte为8位，可用两个十六进制位标识
        char[] buf = new char[bytes.length * 2];
        int a = 0;
        int index = 0;
        for(byte b : bytes) { // 使用除与取余进行转换
            if(b < 0) {
                a = 256 + b;
            } else {
                a = b;
            }

            buf[index++] = HEX_CHAR[a / 16];
            buf[index++] = HEX_CHAR[a % 16];
        }

        return new String(buf);
    }

}
